package com.itxiao.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.itxiao.config.RedisKeyConfig;
import com.itxiao.dao.CartItemDao;
import com.itxiao.dao.SkuDao;
import com.itxiao.dao.SpuDao;
import com.itxiao.dao.SysUserDao;
import com.itxiao.entity.*;
import com.itxiao.pojo.bo.Page;
import com.itxiao.pojo.dto.AddCartDto;
import com.itxiao.pojo.dto.UpdateCartDto;
import com.itxiao.pojo.vo.R;
import com.itxiao.service.CartItemService;
import com.itxiao.util.Price;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * (CartItem)表服务实现类
 *
 * @author makejava
 * @since 2025-10-12 17:07:25
 */
@Service
public class CartItemServiceImpl extends ServiceImpl<CartItemDao, CartItem> implements CartItemService {
    @Resource
    private CartItemDao cartItemDao;
    @Resource
    private SkuDao skuDao;
    @Resource
    private SpuDao spuDao;
    @Resource
    private StringRedisTemplate template;

    @Override
    public R queryList(String token) {
        User sysUser = JSON.parseObject(
                template.opsForValue().get(RedisKeyConfig.AUTH_LOGIN_TOKEN + token),
                User.class
        );
        if (sysUser == null) {
            return R.fail("解析令牌失败");
        }
        List<CartItem> cartItems = cartItemDao.selectList(new LambdaQueryWrapper<>(CartItem.class).eq(CartItem::getUserId, sysUser.getId()));
        Map<String, Object> data = new HashMap<>();
        if (cartItems == null) {
            data.put("list", Collections.emptyList());
            return R.ok(data);
        }
        List<Long> skuIds = cartItems.stream().map(CartItem::getSkuId).collect(Collectors.toList());
        Set<Long> spuIds = cartItems.stream()
                .map(CartItem::getSpuId)
                .collect(Collectors.toSet());
        List<Sku> skus = skuDao.selectList(new LambdaQueryWrapper<>(Sku.class).in(Sku::getId, skuIds));
        if (skus.isEmpty()) {
            return R.fail("查询商品失败");
        }
        List<Spu> spuList = spuDao.selectList(new LambdaQueryWrapper<>(Spu.class).in(Spu::getId, spuIds));
        if (spuList.isEmpty()) {
            return R.fail("查询商品失败");
        }
        // 4. 将 Sku 转为 Map，便于快速查找
        Map<Long, Sku> skuMap = skus.stream()
                .collect(Collectors.toMap(Sku::getId, sku -> sku));
        Map<Long, Spu> spuMap = spuList.stream()
                .collect(Collectors.toMap(Spu::getId, spu -> spu));


        // 5. 遍历购物车项，组装前端需要的完整数据
        List<Map<String, Object>> list = cartItems.stream().map(item -> {
            Map<String, Object> map = new HashMap<>();
            map.put("id", item.getId());
            map.put("userId", item.getUserId());
            map.put("skuId", item.getSkuId());
            map.put("spuId", item.getSpuId());
            map.put("quantity", item.getQuantity());

            Spu spu = spuMap.get(item.getSpuId());
            if (spu != null) {
                map.put("title", spu.getTitle());
                map.put("expressFee", Price.IntToDecimal(spu.getExpressFee()));
                // 可以继续添加其他字段：如库存、规格等
            }
            // 关联商品信息
            Sku sku = skuMap.get(item.getSkuId());
            if (sku != null) {
                map.put("stock", sku.getStock());
                map.put("salePrice", Price.IntToDecimal(sku.getSalePrice()));
                map.put("suggestPrice", Price.IntToDecimal(sku.getSuggestPrice()));
                map.put("thumbnail", sku.getImage());
                // 可以继续添加其他字段：如库存、规格等
            }
            return map;
        }).collect(Collectors.toList());

        // 6. 返回结果
        data.put("list", list);
        return R.ok(data);
    }

    @Override
    public R addOrUpdate(AddCartDto dto, String token) {
        User sysUser = JSON.parseObject(
                template.opsForValue().get(RedisKeyConfig.AUTH_LOGIN_TOKEN + token),
                User.class
        );
        if (sysUser == null) {
            return R.fail("解析令牌失败");
        }
        Long total = cartItemDao.selectCount(new LambdaQueryWrapper<>(CartItem.class).eq(CartItem::getUserId, sysUser.getId()));
        if (total >= 50) {
            return R.fail("购物车最多加入50件商品");
        }
        CartItem cartItem = cartItemDao.selectOne(new LambdaQueryWrapper<>(CartItem.class).eq(CartItem::getUserId, sysUser.getId()).eq(CartItem::getSkuId, dto.getSkuId()));
        if (cartItem == null) {
            CartItem cartItem1 = new CartItem();
            BeanUtils.copyProperties(dto, cartItem1);
            cartItem1.setUserId(sysUser.getId());
            int insert = cartItemDao.insert(cartItem1);
            if (insert <= 0) {
                return R.fail("插入信息失败");
            }
            return R.ok();
        }
        if (dto.getQuantity() < 0 && cartItem.getQuantity() <= Math.abs(dto.getQuantity())) {
            return R.fail("数量异常");
        }
        cartItem.setQuantity(cartItem.getQuantity() + dto.getQuantity());
        int i = cartItemDao.updateById(cartItem);
        if (i <= 0) {
            return R.fail("插入信息失败");
        }
        return R.ok();
    }

    @Override
    public R updateQuantity(UpdateCartDto dto, String token) {
        User sysUser = JSON.parseObject(
                template.opsForValue().get(RedisKeyConfig.AUTH_LOGIN_TOKEN + token),
                User.class
        );
        if (sysUser == null) {
            return R.fail("解析令牌失败");
        }
        CartItem cartItem = cartItemDao.selectOne(new LambdaQueryWrapper<>(CartItem.class).eq(CartItem::getUserId, sysUser.getId()).eq(CartItem::getSkuId, dto.getSkuId()));
        if (cartItem == null) {
            return R.fail("查询购物车商品异常");
        }
        if (dto.getQuantity() <= 0) {
            return R.fail("最低数量1件");
        }
        cartItem.setQuantity(dto.getQuantity());
        int i = cartItemDao.updateById(cartItem);
        if (i <= 0) {
            return R.fail("插入失败");
        }
        return R.ok();
    }
}

